﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Multiprocessing.Core.Units
{
    public class ThreadProcessingBlock : IProcessingBlock
    {
        #region Fields

        private readonly Action[] _actions;
        private readonly Thread[] _threads;

        #endregion

        #region Properties
        
        public Action this[int index]
        {
            get { return _actions[index]; }
            set
            {
                if (_threads[index].IsAlive)
                {
                    throw new ProcessingUnitBlockedException();
                }
                _actions[index] = value;
            }
        }

        public int Size 
        {
            get { return _actions.Length; }
        }

        #endregion

        #region Constructors

        public ThreadProcessingBlock(int size)
        {
            _actions = new Action[size];
            _threads = new Thread[size];
        }

        #endregion

        #region Methods

        public void Dispose()
        {
            
        }

        public void StartAll()
        {
            for (int i = 0; i < this.Size; ++i)
            {
                if (! ReferenceEquals(_actions[i], null))
                {
                    _threads[i] = new Thread(new ThreadStart(_actions[i]));
                    _threads[i].Start();
                }
            }
        }

        public void WaitAll()
        {
            foreach (Thread thread in _threads)
            {
                thread.Join();
            }
        }

        public void StartOne(int index)
        {
            if (ReferenceEquals(_actions[index], null))
            {
                throw new ArgumentException();
            }
            _threads[index] = new Thread(new ThreadStart(_actions[index]));
            _threads[index].Start();
        }

        public void WaitOne(int index)
        {
            _threads[index].Join();
        }

        #endregion
    }
}
